package org.sction.security.shiro;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.sction.security.shiro.api.AccountManager;
import org.springframework.beans.factory.annotation.Autowired;


public class ShiroDbRealm extends AuthorizingRealm {
	private AccountManager accountManager;

	/**
	 * 认证回调函数, 登录时调用.
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		ShiroUser user = accountManager.loadUser(token.getUsername());
		if (user != null) {
			String password = user.getPassword();
			user.setPassword("");
			return new SimpleAuthenticationInfo(user, password, getName());
		} else {
			return null;
		}
	}

	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		ShiroUser shiroUser = (ShiroUser) principals.fromRealm(getName())
				.iterator().next();

		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		Set<String> roles = null;

		if (shiroUser.getRoles() == null
				|| shiroUser.getRoles().trim().equals("")) {
			roles = accountManager.loadRoles(shiroUser.getLoginid());
		} else {
			String[] rs = shiroUser.getRoles().split(",");
			roles = new HashSet<String>();
			for (int i = 0; i < rs.length; i++) {
				roles.add(rs[i]);
			}
		}
		if (roles != null) {
			info.addRoles(roles);

			if (shiroUser.getPops() == null
					|| shiroUser.getPops().trim().equals("")) {
				for (String role : roles) {
					Set<String> pops = accountManager.loadPermissions(role);
					if (pops != null) {
						// 基于Permission的权限信息
						info.addStringPermissions(pops);
					}
				}
			} else {
				String[] ps = shiroUser.getPops().split(",");
				Set<String> pops = new HashSet<String>();
				for (int i = 0; i < ps.length; i++) {
					pops.add(ps[i]);
				}
				info.addStringPermissions(pops);
			}
			return info;
		} else {
			return null;
		}
	}

	/**
	 * 更新用户授权信息缓存.
	 */
	public void clearCachedAuthorizationInfo(String principal) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(
				principal, getName());
		clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除所有用户授权信息缓存.
	 */
	public void clearAllCachedAuthorizationInfo() {
		Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
		if (cache != null) {
			for (Object key : cache.keys()) {
				cache.remove(key);
			}
		}
	}

	@Autowired
	public void setAccountManager(AccountManager accountManager) {
		this.accountManager = accountManager;
	}

}
